package cn.jxwazx.sheinspringboot.service.impl;

import cn.jxwazx.sheinspringboot.entity.BaseNameValue;
import cn.jxwazx.sheinspringboot.entity.QiNiuOssUploadBean;
import cn.jxwazx.sheinspringboot.entity.param.ProductBatchSaveOrUpdateParam;
import cn.jxwazx.sheinspringboot.entity.param.ProductPageParam;
import cn.jxwazx.sheinspringboot.entity.param.Top10Param;
import cn.jxwazx.sheinspringboot.entity.po.ProductList;
import cn.jxwazx.sheinspringboot.entity.vo.ActiveVo;
import cn.jxwazx.sheinspringboot.entity.vo.GMVVo;
import cn.jxwazx.sheinspringboot.entity.vo.ProductExportVO;
import cn.jxwazx.sheinspringboot.entity.vo.Top10ProductVo;
import cn.jxwazx.sheinspringboot.entity.vo.Top10Vo;
import cn.jxwazx.sheinspringboot.mapper.ProductListMapper;
import cn.jxwazx.sheinspringboot.service.ProductListService;
import cn.jxwazx.sheinspringboot.utils.QiNiuUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.dromara.hutool.core.bean.BeanUtil;
import org.dromara.hutool.core.collection.CollStreamUtil;
import org.dromara.hutool.core.collection.CollUtil;
import org.dromara.hutool.core.date.TimeUtil;
import org.dromara.hutool.core.io.file.FileNameUtil;
import org.dromara.hutool.core.io.file.FileUtil;
import org.dromara.hutool.core.math.NumberUtil;
import org.dromara.hutool.core.text.StrUtil;
import org.dromara.hutool.core.thread.AsyncUtil;
import org.dromara.hutool.core.thread.ThreadUtil;
import org.dromara.hutool.core.util.ObjUtil;
import org.dromara.hutool.http.client.HttpDownloader;
import org.dromara.hutool.poi.excel.ExcelUtil;
import org.dromara.hutool.poi.excel.ExcelWriter;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.file.Files;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

/**
 * @author LoveHuaHua
 * @date 2024年03月14日 11:33
 * @description believe in yourself
 */
@Service
@RequiredArgsConstructor(onConstructor = @__(@Lazy))
public class ProductListServiceImpl extends ServiceImpl<ProductListMapper, ProductList> implements ProductListService {

    private final QiNiuUtils ossUtil;
    ExecutorService executorService = ThreadUtil.newExecutor(4, 20);

    public static void main(String[] args) {
        float v = NumberUtil.parseFloat("600+ vendidos recientemente");
        System.out.println(v);
    }

    @Override
    public Collection<ProductList> selectBySkus(Collection<String> skus) {
        if (CollUtil.isEmpty(skus)) {
            return new ArrayList<>();
        }
        return lambdaQuery().in(ProductList::getSku, skus).list();
    }

    /**
     * 批量保存或更新
     *
     * @param params
     */
    @Override
    public void batchSaveOrUpdate(List<ProductBatchSaveOrUpdateParam> params) {

        ThreadUtil.execute(() -> {
            Set<String> set = CollStreamUtil.toSet(params, ProductList::getSku);
            Collection<ProductList> productLists = selectBySkus(set);
            Map<String, ProductList> identityMap = CollStreamUtil.toIdentityMap(productLists, ProductList::getSku);

            for (ProductBatchSaveOrUpdateParam item : params) {
                //是否是列表 0=否 1=是
                boolean listFlag = ObjUtil.isNotNull(item.getListFlag());
                try {
//                    item.setNacionalName(null);
                    ProductList productList = identityMap.get(item.getSku());
                    if (ObjUtil.isNull(productList)) {
                        String sku = item.getSku();
                        String sub = StrUtil.sub(sku, 2, 8);
                        LocalDate yyMMdd = TimeUtil.parseDate(sub, "yyMMdd");
                        //保存
                        item.setUploadDate(yyMMdd);
                        if (listFlag){
                            item.setSyncTime(LocalDateTime.now());
                        }
                        save(item);
                    } else {
                        //更新
                        item.setId(productList.getId());
                        if (listFlag){
                            item.setSyncTime(productList.getCreateTime());
                        }
                        updateById(item);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    log.error(e.getLocalizedMessage());
                }
            }
        });

    }

    @Override
    public List<BaseNameValue<String, String>> getTypeList(Integer type) {
        String typeField = "type_" + type;
        List<BaseNameValue<String, String>> typeList = baseMapper.getTypeList(typeField);
        return typeList;
    }

    /**
     * 导出文件
     *
     * @param param
     * @return
     */
    @Override
    public String exportData(ProductPageParam param) {
        List<ProductList> page = filterProduct(param)
                .list();

        List<ProductExportVO> productExportVOS = BeanUtil.copyToList(page, ProductExportVO.class);
// 通过工具类创建writer
        ExcelWriter writer = ExcelUtil.getWriter(true);
        writer.setOnlyAlias(true);

//自定义标题别名
        writer.addHeaderAlias("productImage", "产品图片");
        writer.addHeaderAlias("productName", "产品名称");
        writer.addHeaderAlias("productPrice", "产品价格");
        writer.addHeaderAlias("productUrl", "产品地址");
        writer.addHeaderAlias("nacionalName", "是否全球");
        writer.addHeaderAlias("startText", "近期评论数");
        writer.addHeaderAlias("nearSaleCount", "90天购买人数");
        writer.addHeaderAlias("sku", "SKU");
        writer.addHeaderAlias("spu", "SPU");
        writer.addHeaderAlias("rank", "排名");
        writer.addHeaderAlias("rankType", "排名情况");
        writer.addHeaderAlias("allCommentScore", "总评价分数");
        writer.addHeaderAlias("allCommentCount", "总评论数量");
        writer.addHeaderAlias("locationCommentScore", "本土评分数");
        writer.addHeaderAlias("locationCommentCount", "本土评数量");
        writer.addHeaderAlias("shopName", "竞品店铺名称");
        writer.addHeaderAlias("shopUrl", "竞品店铺地址");
        writer.addHeaderAlias("shopScore", "竞品店铺总评分数");
        writer.addHeaderAlias("shopProductCount", "竞品店铺总评分数");
        writer.addHeaderAlias("uploadDate", "竞品上架时间");
        writer.addHeaderAlias("updateDayCount", "上架天数");
        writer.addHeaderAlias("joinQuick", "是否参加闪购活动");
        writer.addHeaderAlias("type_1", "一级类目");
        writer.addHeaderAlias("type_2", "二级类目");
        writer.addHeaderAlias("type_3", "三级类目");
        writer.addHeaderAlias("type_4", "四级类目");
        writer.addHeaderAlias("type_5", "五级类目");
        writer.addHeaderAlias("stockCount", "库存情况");
        writer.addHeaderAlias("locationCommentLastTime", "竞品本土评论区最新时间");
        writer.addHeaderAlias("lessFlag", "缺货状态");
        writer.addHeaderAlias("describe", "产品描述");

        writer.write(productExportVOS);
        ArrayList<CompletableFuture<?>> objects = Lists.newArrayList();

        Map<Long, File> map = new HashMap<>();
        for (int i = 0; i < productExportVOS.size(); i++) {
            int finalI = i;
            System.out.println("当前正在导出第:" + finalI + "个");
            ProductExportVO productExportVO = productExportVOS.get(finalI);

            CompletableFuture<Void> voidCompletableFuture = CompletableFuture.runAsync(() -> {
                try {
                    File imgFile = HttpDownloader.downloadFile(productExportVO.getProductImage(), FileUtil.file(
                            FileUtil.getTmpDir() + File.separator + FileNameUtil.getName(
                                    productExportVO.getProductImage())), -1);
                    map.put(productExportVO.getId(), imgFile);
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }, executorService);
            objects.add(voidCompletableFuture);
        }
        AsyncUtil.waitAll(objects.toArray(new CompletableFuture[0]));
        for (int i = 0; i < productExportVOS.size(); i++) {
            try {
                //行高
                writer.setRowHeight(i + 1, 100);

                writer.writeCellValue(0, i + 1, null);
                writer.writeImg(map.getOrDefault(productExportVOS.get(i).getId(), null), 0, i + 1, 1, i + 2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        writer.setColumnWidth(0, 100);
        //自动列宽
        writer.autoSizeColumnAll();

        File file = FileUtil.file(FileUtil.getTmpDir().getAbsolutePath() + File.separator + LocalDateTime.now()
                .format(DateTimeFormatter.ofPattern("yyyyMNddHHmmss")) + "_导出");

        writer.flush(file);

        try {
            QiNiuOssUploadBean qiNiuOssUploadBean = ossUtil.uploadFileByStream(Files.newInputStream(file.toPath()),
                    "shein/" + file.getName(), "xlsx");
            return qiNiuOssUploadBean.getUrl();

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<GMVVo> selectGMV() {
        List<GMVVo> gmvVos = baseMapper.selectGMV();
        for (GMVVo gmvVo : gmvVos) {
            double locationGMVRadio = gmvVo.getLocationGMV() / gmvVo.getAllGMV();
            BigDecimal round = NumberUtil.round(locationGMVRadio, 2);
            gmvVo.setLocationGMVRadio(round);
            gmvVo.setAllLocationGMVRadio(NumberUtil.sub("100", String.valueOf(round)));
        }
        return gmvVos;
    }

    @Override
    public void fix() {
        List<ProductList> list = lambdaQuery().isNull(ProductList::getNearSaleCountInt).or().isNull(ProductList::getProductPriceDecimal).list();
        for (ProductList productList : list) {
            try {
                if (StrUtil.isEmpty(productList.getType1())) {
                    productList.setType1(productList.getType2());
                }
                //产品价格
                String price = productList.getProductPrice().replaceAll("\\$MXN", "");

                System.out.println(price);
                System.out.println(productList);
                productList.setProductPriceDecimal(BigDecimal.valueOf(NumberUtil.parseFloat(price)));
                //购买数量
                float count = NumberUtil.parseFloat(productList.getNearSaleCount());
                if (productList.getNearSaleCount().contains("k")) {
                    count = count * 1000;
                }

                productList.setNearSaleCountInt((int) count);
                updateById(productList);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public List<ActiveVo> active() {
        List<ActiveVo> activeVos = baseMapper.selectActive();
        for (ActiveVo activeVo : activeVos) {
            double locationGMVRadio = (double) activeVo.getLocationCount() / activeVo.getProductCount();
            BigDecimal round = NumberUtil.round(locationGMVRadio, 2);
            activeVo.setLocationRadio(round);
            BigDecimal sub = NumberUtil.sub("100", String.valueOf(round));
            activeVo.setAllLocationRadio(sub);
        }
        return activeVos;
    }

    @Override
    public LambdaQueryChainWrapper<ProductList> filterProduct(ProductPageParam param) {
        return lambdaQuery().eq(StrUtil.isNotBlank(param.getJoinQuick()),
                        ProductList::getJoinQuick, param.getJoinQuick())
                .like(StrUtil.isNotBlank(param.getProductName()), ProductList::getProductName, param.getProductName())
                .like(StrUtil.isNotBlank(param.getSku()), ProductList::getSku, param.getSku())
                .like(StrUtil.isNotBlank(param.getSpu()), ProductList::getSpu, param.getSpu())
                .eq(StrUtil.isNotBlank(param.getLessFlag()), ProductList::getLessFlag, param.getLessFlag())
                .eq(StrUtil.isNotBlank(param.getType1()), ProductList::getType1, param.getType1())
                .eq(StrUtil.isNotBlank(param.getType2()), ProductList::getType2, param.getType2())
                .eq(StrUtil.isNotBlank(param.getType3()), ProductList::getType3, param.getType3())
                .eq(StrUtil.isNotBlank(param.getType4()), ProductList::getType4, param.getType4())
                .eq(StrUtil.isNotBlank(param.getType5()), ProductList::getType5, param.getType5())
                .eq(StrUtil.isNotBlank(param.getNacionalName()), ProductList::getNacionalName, param.getNacionalName())
                .le(StrUtil.isNotBlank(param.getLowPrice()), ProductList::getProductPriceDecimal, param.getLowPrice())
                .ge(StrUtil.isNotBlank(param.getHighPrice()), ProductList::getProductPriceDecimal, param.getHighPrice())
                ;
    }

    /**
     * top10
     *
     * @param param
     * @return
     */
    @Override
    public Page<Top10Vo> top10(Top10Param param) {
        return baseMapper.top10(param.getPage(), param);
    }

    @Override
    public Page<Top10ProductVo> top10Product(Top10Param param) {
        Page<Top10ProductVo> top10ProductVoPage = baseMapper.top10Product(param.getPage(), param);
//        ArrayList<Top10ProductVo> records = Lists.newArrayList();
//        for (Top10ProductVo record : top10ProductVoPage.getRecords()) {
//            ProductList productList = getById(record.getId());
//            Top10ProductVo top10ProductVo = BeanUtil.copyProperties(productList, Top10ProductVo.class);
//            top10ProductVo.setRankNumber(record.getRankNumber());
//            records.add(top10ProductVo);
//        }
//        Page<Top10ProductVo> top10ProductVoPage1 = new Page<>();
//        top10ProductVoPage1.setTotal(top10ProductVoPage.getTotal());
//        top10ProductVoPage1.setRecords(records);
        return top10ProductVoPage;
    }
}
